package com.sxz.mall.member.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sxz.mall.common.utils.HttpUtils;
import com.sxz.mall.member.entity.MemberLevelEntity;
import com.sxz.mall.member.exception.PhoneExistException;
import com.sxz.mall.member.exception.UserNameExistException;
import com.sxz.mall.member.service.MemberLevelService;
import com.sxz.mall.member.vo.MemberLoginVO;
import com.sxz.mall.member.vo.MemberRegisterVO;
import com.sxz.mall.member.vo.SocialUser;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sxz.mall.common.utils.PageUtils;
import com.sxz.mall.common.utils.Query;

import com.sxz.mall.member.dao.MemberDao;
import com.sxz.mall.member.entity.MemberEntity;
import com.sxz.mall.member.service.MemberService;


@Service("memberService")
public class MemberServiceImpl extends ServiceImpl<MemberDao, MemberEntity> implements MemberService {

    @Autowired
    MemberLevelService memberLevelService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<MemberEntity> page = this.page(
                new Query<MemberEntity>().getPage(params),
                new QueryWrapper<MemberEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 完成会员注册功能
     *
     * @param vo
     */
    @Override
    public void register(MemberRegisterVO vo) throws UserNameExistException, PhoneExistException {
        MemberEntity memberEntity = new MemberEntity();

        // 设置数据库中对应的默认等级（普通，黄金，钻石....）
        MemberLevelEntity levelEntity = memberLevelService.queryDefaultMemberLevel();
        memberEntity.setLevelId(levelEntity.getId());

        // 校验账号、手机号，不能是数据库中已经有的
        checkPhoneUnique(vo.getPhone());
        checkUsernameUnique(vo.getUserName());

        memberEntity.setUsername(vo.getUserName());
        memberEntity.setMobile(vo.getPhone());

        // 密码不能保存为明文  注意加密规则  md5,或者sha256   可逆，不可逆   穷举 盐来做确认，可以大概率的逆推出密码
        // 底层是： 加盐  盐会打乱存在于密文中   故而每次加密后返回的密文都不一样    但是matches可以校验到
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        memberEntity.setPassword(encoder.encode(vo.getPassword()));

        // 设置其他默认值

        this.save(memberEntity);
    }

    @Override
    public MemberEntity login(MemberLoginVO vo) {

        // 根据手机号或者用户名来查询用户信息
        MemberEntity memberEntity = this.getOne(new QueryWrapper<MemberEntity>()
                .eq("username", vo.getUserName())
                .or()
                .eq("mobile", vo.getUserName())
        );
        // 校验密码是否正确
        if (memberEntity != null) {
            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
            boolean matches = encoder.matches(vo.getPassword(), memberEntity.getPassword());
            if (matches) {
                return memberEntity;
            }
        }

        return null;
    }

    /**
     * 社交登录
     *
     * @param vo
     * @return
     */
    @Override
    public MemberEntity login(SocialUser vo) {
        // 前置处理，数据库表中，添加字段，实体类添加对应字段
        // 第一次社交登录，需要注册， 更新对应字段值到数据库
        // 不是第一次登录，就更新处理
        MemberEntity memberEntity = this.getOne(new QueryWrapper<MemberEntity>().eq("social_uid", vo.getUid()));
        MemberEntity entity = new MemberEntity();
        entity.setSocialUid(vo.getUid());
        entity.setAccessToken(vo.getAccessToken());
        entity.setExpiresIn(vo.getExpiresIn());
        if (memberEntity != null) {
            entity.setId(memberEntity.getId());

            this.update(new QueryWrapper<MemberEntity>().eq("id", entity.getId()));

            return entity;
        }

        // 第一次，需要注册，单起一行数据来存储即可
        try {
            Map<String, String> querys = new HashMap<>();
            querys.put("access_token", vo.getAccessToken());
            querys.put("uid", vo.getUid());
            HttpResponse response = HttpUtils.doGet("https://api.weibo.com",
                    "/2/users/show.json",
                    "get",
                    new HashMap<>(),
                    querys);
            if (response.getStatusLine().getStatusCode() == 200) {
                String json = EntityUtils.toString(response.getEntity());
                JSONObject jsonObject = JSON.parseObject(json);
                String nickName = jsonObject.getString("screen_name");
                String gender = jsonObject.getString("gender");

                entity.setNickname(nickName);
                entity.setGender("m".equals(gender) ? 1 : 0);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        this.save(entity);
        return entity;
    }

    private void checkUsernameUnique(String userName) throws UserNameExistException {
        int usernameCount = this.count(new QueryWrapper<MemberEntity>().eq("username", userName));
        if (usernameCount > 0) {
            throw new UserNameExistException();
        }
    }

    private void checkPhoneUnique(String phone) throws PhoneExistException {

        int phoneCount = this.count(new QueryWrapper<MemberEntity>().eq("mobile", phone));
        if (phoneCount > 0) {
            throw new PhoneExistException();
        }
    }


}